#!/usr/bin/env lua
-- mps lua kodlaması

-- IMPORT --
local milispath=os.getenv("MILIS_PATH")
if not milispath then milispath="/usr/milis" end

local talimatname=os.getenv("TALIMATNAME")
if not talimatname then talimatname=milispath.."/".."talimatname" end

local mps_path=os.getenv("MPS_PATH")
if not mps_path then mps_path=milispath.."/".."mps" end

package.cpath = package.cpath .. ";"..mps_path.."/lua/?.so"
package.path = package.path .. ";"..mps_path.."/lua/?.lua"
package.cpath = package.cpath .. ";"..mps_path.."/lua/ext/?.so"
package.path = package.path .. ";"..mps_path.."/lua/ext/?.lua"
package.path = package.path .. ";"..mps_path.."/lang/?.lua"
package.path = package.path .. ";"..mps_path.."/conf/?.lua"
-- local socket = require("socket")
local lip= require("LIP")
local lfs = require("lfs")
-- socket src e eklenecek todo!!!
local http = require("socket.http")
-- local tparser= require("tparser")
-- mpsd talimat modülüne aktarılacak todo!!!
local t=require ("talimat")

local util=require ("mps_helper")
local yaz=util.yaz
local _assert=util._assert
local has_value=util.has_value
local path_exists=util.path_exists
local shell=util.shell
local get_abspath=util.get_abspath
local get_basename=util.get_basename
local get_dirname=util.get_dirname
local get_size=util.get_size
local get_content=util.get_content
local get_dirs=util.get_dirs
local has_line=util.has_line
local tprint=util.tprint
local hash_check=util.hash_check


-- dil tespiti / sonra mps-helper den çağrılabilir.
local _langenv=os.getenv("LANG")
if not _langenv then _langenv="tr_TR" end
local _langvar,_=_langenv:match("(.*)_(.*)")
local messages = require ("lang_".. _langvar)
--------------------------------------------------

-- mps ile ilgili ayarların conf/conf.lua dan yüklenmesi
if not path_exists(mps_path.."/conf/conf.lua") then
	shell("cp "..mps_path.."/conf/conf.lua.sablon "..mps_path.."/conf/conf.lua")
	messages.default_configs_loaded:yaz(2)
	messages.relaunch_mps:yaz(2)
	os.exit()
end
local ayar= require ("conf")
-------------------------------------------------------

-- DIZIN OLUŞTURMA - KONTROL --

-- Paketleme dizini, yürürlük dosyasının oluşturulduğu konum
local paketleme_dizin=os.getenv("PAKETLEME_DIZIN")
if not paketleme_dizin then paketleme_dizin=lfs.currentdir() end

-- GLOBAL VARIABLES --

local arsivci="bsdtar"
local params={}
local islem={}
islem.api={}

-- local talimatname="/usr/milis/talimatname"							
local kokdizin=""
local sil_onay=false
local paket_arsiv_pattern="([%a%d-+]+)#([%d%a.]+)-([%d]+)-([%a%d_]+)" -- paket_isim#surum-devir-mimari : abc#1.2.3-1-x86_64
-- paket arşiv format -paket_isim#surum-devir-mimari.mps.lz
local paf="%s#%s-%s-%s.mps.lz"
-- paket gösterim formatı
local pgf="%s#%s-%s"
-- paket depo link formatı - depo_adres/paket_isim#surum-devir-mimari.mps.lz / paf kullan
local plf="%s/%s"
-- hata takip -debug modu
debug=false

-- GLOBAL İŞLEVLER

-- root yetkili kontrolü
function authorised_check()
	if not os.getenv("MPS_NOROOT") then 
		local me=os.getenv("USER")
		if me ~= "root" then
			messages.need_root:yaz(0)
		end
	end
end

-- parametre analiz/ color option check
function color_check()
	for index, a in ipairs(params) do 
		if a then
			local var = a:match("^-%-color=(.*)$") 
			if var then 
				if var =="0" then util.renkli=false end
				if var =="1" then util.renkli=true end
				params[index]=false
				break
			end
		end
	end
end

-- parametre analiz/ debug mode
function debug_check()
	for index, a in ipairs(params) do 
		if a then
			local var = a:match("^-%-debug(.*)$") 
			if var then 
				debug=true
				params[index]=false
				break
			end
		end
	end
end

-- parametre analiz/ package management root check
function root_check()
	-- öntanımlı olarak / altına paket işlemlerini yapar.
	kokdizin="/"
	for index, a in ipairs(params) do 
		if a then
			local var = a:match("^-%-kok=(.*)$") 
			if var then 
				-- kokdizin sonunda / yoksa eklenir, altdizinlerde lazım
				if var:sub(-1) ~= "/" then var=var.."/" end
				kokdizin=var
				params[index]=false
				break
			end
		end
	end
	-- kok dizin kontrolü yapıldıktan sonra alt dizin kontrolleri
	-- milis dizini yoksa oluşturuyoruz.
	if path_exists(milispath) == false then
		shell("mkdir -p "..kokdizin..milispath)
	end

	-- talimat dizini yoksa oluşturuyoruz.
	if path_exists(talimatname) == false then
		shell("mkdir -p "..kokdizin..talimatname)
	end
end

function mps_init()
	-- mps için gerekli dizinlerin oluşturulması
	-- /var/lib/mps/db
	local create_tmp=("mkdir -p %s"):format(kokdizin.."tmp")
	local create_db=("mkdir -p %s"):format(kokdizin..islem.paket.vt)
	local create_logs=("mkdir -p %s%s"):format(kokdizin,islem.paket.logdir)
	local create_log_k=("mkdir -p %s%s"):format(kokdizin,islem.kur.logdir)
	local create_log_s=("mkdir -p %s%s"):format(kokdizin,islem.sil.logdir)
	local create_cache=("mkdir -p %s%s"):format(kokdizin,islem.paket.cachedir)
	shell(create_tmp)
	shell(create_db)
	shell(create_logs)
	shell(create_log_k)
	shell(create_log_s);
	shell(create_cache);
	(messages.init_is_ok..kokdizin):yaz()
end

-- parametre analiz/ mps vt dir structure check
function mps_init_check()
	-- öntanımlı olarak / altına paket işlemlerini yapar.
	for index, a in ipairs(params) do 
		if a then
			local var = a:match("^-%-ilk") 
			if var then 
				mps_init()
				params[index]=false
				break
			end
		end
	end
end

-- mps dosya sistemi ilkleme
function mps_initfs()
	-- Milis için gerekli dizinlerin oluşturulması
	local initfs_komut=("bash %s/conf/init_rootfs.sh %s"):format(mps_path,kokdizin)
	shell(initfs_komut);
	--print(initfs_komut);
	(messages.initfs_is_ok..kokdizin):yaz()
end

-- parametre analiz/ mps dosya sistemi ilkleme
function mps_initfs_check()
	-- öntanımlı olarak / altına paket işlemlerini yapar.
	for index, a in ipairs(params) do 
		if a then
			local var = a:match("^-%-initfs") 
			if var then 
				mps_initfs()
				params[index]=false
				break
			end
		end
	end
end

-- mps işlemlerindeki onay değerini kontrol eder.
function confirm_check()
	-- --yes, --ona değerlerini kontrol eder.
	for index, a in ipairs(params) do 
		if a then
			local var = a:match("^-%-yes") 
			local var = a:match("^-%-ona") 
			if var then 
				sil_onay=true
				params[index]=false
				break
			end
		end
	end
end

-- parametrelerden işşlenmiş olanları silerek hedef işleve kalanı gönderir.
function re_param()
	_param={}
	for _, val in ipairs(params) do
		if val then table.insert(_param,val) end
	end 
	params=_param
end

function sleep(n)
  -- waits for the passed time, letting the coroutine world spin
  local t0 = os.clock()
  while os.clock() - t0 <= n do 
	coroutine.yield()
  end
end

-- Diyalog İşlemleri

islem.diyalog={}

function islem.diyalog.onay(mesaj)
	local answer="-"
	if mesaj == nil then mesaj="?(y/n)" end
	repeat
	io.write(mesaj)
	io.flush()
	answer=io.read()
	until answer=="y" or answer=="n" or answer=="e" or answer=="h" 
	if answer=="y" or answer=="e" then return true
	else return false end
end

-- MPS İŞLEMLER

-- talimat bul
islem.talimat_bul={
	retkey="talimat_bul:",
}
islem.bul={usage="mps bul talimat_isim",}

function islem.talimat_bul.job(paket,tip)
	-- alfanumerik arama yapılır.
	-- 2.parametere tip=hepsi gönderilirse bütün arama sonuçları çevirilir.
	local komut=('find %s -name "%s#*" | sort -n | head -1'):format(talimatname,paket)
	if tip=="hepsi" then
		komut=('find %s -name "*%s*" -type d | sort -n'):format(talimatname,paket)
	end
	--print(komut)
	ret=shell(komut)
	if ret == "" then
		return false
	else
		return ret
	end
end

-- talimat bulma işlevi (mps bul talimat_isim)
function islem.bul.handler(input)
	-- todo!!! talimat bul a diğer talimatlar varsa da ek parametre ile gösterilecek
	-- veya mps ara(tanım-paket ismi) içine yapılacak. !
	if #input == 2 then
		-- 1 is talimat_bul işlemi
		local _islem=input[1]
		local talimat=input[2]
		-- bütün eşleşen talimatlar bulunacak
		local ret=islem.talimat_bul.job(talimat,"hepsi")
		if ret then
			print(ret)
		else
			messages.talimat_not_found:yaz(0)
		end
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

--

-- Kaynak işlemleri
islem.kaynak={
	usage="mps kaynak talimat_ismi",
	kontrol=false,
}

-- kaynak talimatın içerdiği kaynakları gösterecek
function islem.kaynak.handler(input)
	local liste={}
	if #input > 1 then
		-- 1 is talimat_bul işlemi
		local _islem=input[1]
		local girdi=input[2]
		local param=input[3]
		local dosya = girdi:match("^-%-dosya=(.*)$") 
		
		if param and param:match("--kontrol") then islem.kaynak.kontrol=true end
		if dosya then
			if path_exists(dosya) then
				islem.kaynak.liste_dosyadan(dosya)
			else
				messages.file_not_found:format(dosya):yaz(0)
			end
		else
			-- girdi parametresi talimat olarak değerlendirelecek.
			local ret=islem.talimat_bul.job(girdi)
			if ret then
				-- kaynaklar kontrol edilecekse
				if islem.kaynak.kontrol then
					islem.kaynak.url_kontrol(islem.kaynak.liste(ret))
				-- kontrol yoksa sadece listeleme
				else
					tprint(islem.kaynak.liste(ret))
				end
			else
				messages.talimat_not_found:yaz(0)
			end
		end
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

-- talimata ait kaynakların listelenme işlevi
function islem.kaynak.liste(talimatd)
	assert(path_exists(talimatd),"talimat dizin not found!")
	local talimatf=talimatd.."/talimat"
	assert(path_exists(talimatf),talimatf.." file not found!")
	-- talimat dosyasından alınan kaynaklar bash ile yorumlanıp
	-- açık değerlerine çevirlecektir.
	local kliste={}
	local talimat=t.get(talimatd)
	local komut='url=%s && isim=%s && surum=%s && devir=%s && echo '
	komut=komut:format(talimat.paket.url,talimat.isim,talimat.surum,talimat.devir)
	for _,val in ipairs (t.kaynaklar(talimat)) do
		table.insert(kliste,shell(komut..val))
	end
	return kliste
end

-- dosyadaki talimata ait kaynakların listelenme işlevi
function islem.kaynak.liste_dosyadan(dosya)
	local ret=nil
	for pk in (get_content(dosya)):gmatch("[^\r\n]+") do 
		ret=islem.talimat_bul.job(pk)
		if ret then
			-- kaynaklar kontrol edilecekse
			if islem.kaynak.kontrol then
				islem.kaynak.url_kontrol(islem.kaynak.liste(ret))
			-- kontrol yoksa sadece listeleme
			else
				tprint(islem.kaynak.liste(ret))
			end
		else
			messages.talimat_not_found:yaz(0)
		end
	end
end

-- talimata ait kaynakların url aktif kontrolü
function islem.kaynak.url_kontrol(kaynaklar)
	local komut="wget -q --spider %s && echo $?"
	local ret=""
	for _,kaynak in ipairs(kaynaklar) do
		if kaynak:match("http") or kaynak:match("https") then 
			ret=shell(komut:format(kaynak))
			if ret == "0" then
				print(kaynak, "OK")
			else
				print(kaynak, "NOT")
			end
		else
			print(kaynak, "PASS")
		end
	end
end


-------

---------- Gerekler İşlemler ----------

islem.gerek={
	retkey="gerek:",
	usage="mps gerek paket_ismi tip",
	-- aktif gerek listesi
	liste={},
	-- aktif gereklerin eklenme kontrol listesi
	list={},
}

function islem.gerek.job(talimatd,tip)
	assert(talimatd,"talimatd is nil!")
	local talimat=t.get(talimatd)
	--todo!!! sonsuz gerek döngüsü engellenecek.
	-- gereklerin toplanan listeye eklenmesi
	local function ekle(talimatd)
		if islem.gerek.list[talimatd] == nil then
			islem.gerek.list[talimatd]=talimatd
			--print("e",talimatd)
			table.insert(islem.gerek.liste,talimatd)
		end
	end
	
	-- talimatın libgerekler dosyasının analiz edilmesi
	local function oto_rdeps(talimatd)
		if path_exists(talimatd.."/"..islem.shlib.dosya) then
			local sh_tal=""
			local shlibs=get_content(talimatd.."/"..islem.shlib.dosya)
				for sh in shlibs:gmatch("[^\r\n]+") do 
					sh_tal=islem.shlib.bul(sh,"-t","ilk")
					if sh_tal and sh_tal ~= talimatd then
						--print("3",sh_tal)
						islem.gerek.job(sh_tal,"c")
					end
				end
		end
	end
	
	-- alt gereklerin dolaşılması
	local function gerek_dolas(dep,talimatd)
		local _td=islem.talimat_bul.job(dep)
		-- bir önceki paketin kurulabilir değeri iptal ediliyor
		local kurulabilir=false
		if _td then
			-- bir paketin depodaki bulunma durumuna göre
			-- derleme ve çalışma gereklerinin araştırılması yapılmaktadır.
			-- çalışma gerek araşırılmasında da aynı durum kontrol edilmektedir.
			-- todo!!! alt işleve alınacak alttaki operasyon
			tsd=get_basename(_td)
			for _,b in ipairs(islem.paket.pkvt_bilgi(dep)) do
				pksd=pgf:format(b.isim,b.surum,b.devir)
				if tsd == pksd then
					kurulabilir=b
					break
				end
			end
			if kurulabilir then
				tip="c"
			else
				tip="d"
			end
			
			islem.gerek.job(_td,tip)
		else
			(messages.talimat_not_found..talimatd..":"..dep):yaz(0)
		end
	end
	
	-- talimatdaki gerek kısmının analiz edilmesi - ana iskelet
	if talimat["gerek"] then
		local rdeps=talimat["gerek"]["calisma"]
		local bdeps=talimat["gerek"]["derleme"]
		local kurulabilir=false
		if tip == "d" and bdeps then
			for dep in bdeps:gmatch('([^%s]+)') do
				gerek_dolas(dep,talimatd)
			end
		elseif rdeps then
			for dep in rdeps:gmatch('([^%s]+)') do
				gerek_dolas(dep,talimatd)
			end
		end
		oto_rdeps(talimatd)
		ekle(talimatd)
	else
		oto_rdeps(talimatd)
		ekle(talimatd)
	end
	
end

function islem.gerek.handler(input)
	if #input > 2 then
		-- 1 is derle işlemi
		local _islem=input[1]
		local girdi=input[2]
		local tip=input[3]
		-- tip (d)erleme veya (c)alışma olmalı
		if tip ~= "d" and tip ~="c" then
			("invalid dependency type"):yaz(0)
		end
		local talimatd=islem.talimat_bul.job(girdi)
		if talimatd then
			islem.gerek.job(talimatd,tip)
			print("gerekler")
			print("-------------------")
			tprint(islem.gerek.liste)
			print("-------------------")
		else
			(messages.args_invalid..girdi):yaz(0)
		end
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
	
end

islem.tgerek={
	retkey="tgerek:",
	usage="mps tgerek paket_ismi tip",
	comment=messages.comment_mps_rev_dep,
}

function islem.tgerek.handler(input)
	--todo!!! derleme ve calisma ayrılacak
	-- input>2 olacak tip te eklenirse
	if #input > 1 then
		-- 1 is derle işlemi
		local _islem=input[1]
		local girdi=input[2]
		local tip=input[3]
		-- tip (d)erleme veya (c)alışma olmalı
		if tip ~= "d" and tip ~="c" then
			("Geçersiz gekelilik tipi!"):yaz(0)
		end
		local talimatd=islem.talimat_bul.job(girdi)
		if talimatd then
			islem.tgerek.job(girdi, tip)
		else
			(messages.args_invalid..girdi):yaz(0)
		end
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
	
end

function islem.tgerek.job(paket, tip)
	print("Ters gerekler:");
	print("-------------------")
	local local_paketler={}
	if tip == "d" then
		-- derleme
		local komut="grep -r ' *derleme *= *' %s | grep  ' %s$\\| %s \\|=%s$\\|=%s ' | cut -d':' -f1 | xargs -I {} dirname {} | xargs -I {} basename {} | cut -d'#' -f1"
		ret=shell(komut:format(talimatname,paket,paket,paket,paket))
		for line in ret:gmatch("[^\r\n]+") do 
			table.insert(local_paketler, line)
		end
	else
		-- calistirma
		-- talimat dosyasindan
		local komut="grep -r ' *calisma *= *' %s | grep  ' %s$\\| %s \\|=%s$\\|=%s ' | cut -d':' -f1 | xargs -I {} dirname {} | xargs -I {} basename {} | cut -d'#' -f1"
		ret=shell(komut:format(talimatname,paket,paket,paket,paket))
		for line in ret:gmatch("[^\r\n]+") do 
			table.insert(local_paketler, line)
		end
		-- libgerek dosyasindan
		local talimatd=islem.talimat_bul.job(paket)
		if path_exists(talimatd.."/".."pktlibler") then
			local sh_tal=""
			local shlibs=get_content(talimatd.."/".."pktlibler")
				for sh in shlibs:gmatch("[^\r\n]+") do 
					local komut=("grep -ril --include=libgerekler '%s$' %s | xargs -I {} dirname {} | xargs -I {} basename {} | cut -d'#' -f1"):format(sh,talimatname)
					sh_tal=shell(komut)
					for line in sh_tal:gmatch("[^\r\n]+") do 
						if not has_value(local_paketler, line) then
							table.insert(local_paketler, line)
						end
					end
				end
		end
	end
	tprint(local_paketler)
	print("-------------------")
end

------------------------------------------

-- Derle işlemi 

islem.derle={
	retkey="derle:",
	usage="mps derle paket_ismi",	
}

--api
-- -d tekli paket derlemesi
islem.api.d={
	usage="",
	comment="",
}

islem.api.d.job=function (params) 
	local pk=params[2];return islem.derle.tekli(pk)
end

function islem.derle.handler(input)
	if #input > 1 then
		-- 1 is derle işlemi
		-- todo!!! genel param analiz yer değiştirmeli
		local _islem=input[1]
		local talimat=input[2]
		local hedefkur=input[3]
		islem.derle.job(talimat,hedefkur)
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

function islem.derle.job(paket,hedefkur)
	--talimat konum bul
	local ret=islem.talimat_bul.job(paket)
	local retq=nil
	-- pk   = paket isim
	-- pksd = ağdaki paket sürüm-devir
	-- tsd  = talimat sürüm-devir
	-- ksd  = kurulu sürüm-devir
	local pk,pksd,tsd,ksd=""
	local derlet=false
	local kurulabilir=false
	local eski_sil=false
	if ret then
		-- derleme işlemi
		-- todo!!! mpsd.lua lib olarak çağrılacak sonra, şu an shell
		-- 1. Derleme gerekleri bul.
		islem.gerek.job(ret,"d")
		--tprint(islem.gerek.liste)
		-- 2. Döngüde gerekler incelenir.
		for _,talimatd in ipairs(islem.gerek.liste) do
			-- her gerekte derletme ve kurulma durumları sıfırlanacak.
			derlet=false
			kurulabilir=false
			-- 2.1 kurulu kontrol
			tsd=get_basename(talimatd)
			pk,_=tsd:match("([%a%d-+]+)#+")
			-- kurulu kontrol , link dizin dönüşü ile
			ksd=islem.paket.kurulu_kontrol(pk)
			-- 2.1.1 paket kurulu ise sürüm-devir uyum kontrolü yapılır.
			if ksd then
				-- ksd kurulu yol, sadece talimat isim formatı
				ksd=get_basename(ksd)
				if tsd ~= ksd then
					print("kurulu sürümd ile derlenmesi gereken sürümd farklı-derlenecek!")
					-- paket kurulu sd uyumsuzluğu var
					-- paketi sildir(onaylı?) ve derlet
					-- önemli !!!-eski paketi derleme başarılı olursa sildir.
					derlet=true
					eski_sil=true
				else
					messages.package_already_installed_and_uptodate:format(pk):yaz(2)
					goto continue
				end
			-- 2.1.2 paket kurulu değilse ağdan indirilip kurulacak
			end
			-- ağdaki paketin surumdeviri incelenecek
			-- tsd ile pksd karşılaştır
			-- paket.vt lerdeki paket sürüm-devir bilgileri taranacak.
			-- tsd e eşleşen bulunursa eşleşen! indirilecek yoksa derletilecek.
			-- pakete ait depolarda bulduğu pkvt bilgisini getirecek.
			for _,b in ipairs(islem.paket.pkvt_bilgi(pk)) do
				pksd=pgf:format(b.isim,b.surum,b.devir)
				if tsd == pksd then
					print(pk,b.depo,"bulundu.")
					kurulabilir=b
					break
				end
			end
			-- kurulabilir nesnesine ağdaki paket bilgisi atılacak.
			if kurulabilir then
				-- paket önbellekte varsa 
				-- shasum kontrolü yapılıp yerelden kurulma yapılacak.
				-- ağdan indirmeden önce önbellekte kontrol edecek
				local _pkt=paf:format(pk,kurulabilir.surum,kurulabilir.devir,kurulabilir.mimari)
				local kur_onay=false
				local _indir=false
				local _pktyol=kokdizin..islem.paket.cachedir.."/".._pkt
				if path_exists(_pktyol) then
					print("hash kontrol")
					if hash_check(_pktyol,kurulabilir.shasum) == false then
						--delete file
						shell("rm -f ".._pktyol)
					end
					_indir=true
				else
				   -- önbellekte yoksa veya hash uyumsuzsa indirilecek
				   _indir=true 
				end
				if _indir then
					print(_pkt,"indirilecek")
					islem.indir.handler({nil,pk})
				end
				-- indirilememe veya herhangi bir nedenden paketin önbellekte hazır olmaması durumu
				if not path_exists(_pktyol) then 
					messages.package_not_found:format(_pktyol):yaz(0)
				else
					-- ağdan inen veya önbellekteki paket kurulabilir
					-- ayrıca eski paket kurulu ise kaldırılacak.
					if eski_sil then
						print("eski sürüm paket tespit edildi, kaldırılacak")
						islem.sil.handler({"",pk})
					end
					print(_pktyol,"kurulacak")
					islem.kur.yerelden(_pktyol)
					-- paket kurulduysa eğer eski sürümden dolayı onay verilen derletme
					-- işlemi iptal edilecektir.
					derlet=false
				end
			else
				derlet=true
			end
			
			-- 2.2 derleme
			if derlet then
				-- aktif oluşan paket arşiv
				local mimari=shell("uname -m")
				local pkarsiv=tsd.."-"..mimari..".mps.lz"
				-- hedef paket isimleri
				local hpksd=get_basename(ret)
				local hdarsiv=hpksd.."-"..mimari..".mps.lz"
				-- 2.2.1 talimat derle
				print(talimatd,"tl derlenecek")
				-- print(ret.." derlenecek")
				retq=shell("mpsd.lua "..talimatd)
				-- paketleme dizinine geçilir.
				lfs.chdir(paketleme_dizin)
				assert(path_exists(pk..".yur"),"islem.derle.job : "..pk..".yur not found")
				os.execute(("bash ./%s.yur"):format(pk))
				-- 2.2.2 üretilen paketi kur
				-- hedef üretilmek istenen pakete gelindiğinde
				-- bu noktada derleme başarılı olup paket üretildiği
				-- kontrol edilerek eski sürüm paket kaldırılır.
				
				if pk == paket then
					-- mps derle paket --kur seçeneğine bakılacak.
					if hedefkur=="--kur" then
						-- hedef paket arşivi
						if path_exists(paketleme_dizin.."/"..hdarsiv) then
							if eski_sil then islem.sil.handler({"",pk}) end
							print(paket.." hedef paket de kurulacak.")
							islem.kur.yerelden(paketleme_dizin.."/"..hdarsiv)
						else
							messages.package_not_found:format(hdarsiv):yaz(0)
						end
					end
				else
					-- altgereklerin oluşan paketleri zorunlu kurulacak
					if path_exists(paketleme_dizin.."/"..pkarsiv) then
						if eski_sil then islem.sil.handler({"",pk}) end
						islem.kur.yerelden(paketleme_dizin.."/"..pkarsiv)
					else
						messages.package_not_found:format(pkarsiv):yaz(0)
					end
				end
			end
			::continue::
		-- for bitiş
		end
		--print(paket.." derleme bitti")
	else
		(messages.talimat_not_found..paket):yaz(0)
	end
end

function islem.derle.tekli(paket)
	--talimat konum bul
	ret=islem.talimat_bul.job(paket)
	if ret then
		print(ret.." derlenecek")
		retq=shell("mpsd.lua "..ret)
		--print (retq)
		-- paketleme dizinine geçilir.
		lfs.chdir(paketleme_dizin)
		-- os.exit()
		assert(path_exists(paket..".yur"),"islem.derle.job : talimat.yur not found")
		os.execute(("bash ./%s.yur"):format(paket))
	else
		(messages.talimat_not_found..paket):yaz(0)
	end
end

------------------------------

-- Paket Arşiv işlemleri
islem.arsiv={
	retkey="arşiv:",	
}

-- Milis paketi ön kontrolleri
function islem.arsiv.kontrol(paket)
	-- kullanıcı hedefli de çıktı verilebilinir.
	assert(path_exists(paket),"islem.arsiv.kontrol : paket is not found")
	assert(paket:match("mps.lz"),"islem.arsiv.kontrol : paket suffix is not mps.lz")
	assert(get_size(paket) ~=0,"islem.arsiv.kontrol : paket size equals zero")
	
	local isd = get_basename(paket)
	local isim,surum,devir,mimari=isd:match(paket_arsiv_pattern)
	if not (isim and surum and devir and mimari) then
		print(messages.valid_format..paf:format(isim,surum,devir,mimari));
		(messages.package_name_format_not_valid..isd):yaz(0)
	end
	-- bir kontrol de tar ile içeriden paket bilgi dosyası çekilebilir
	-- bu kontrol extract den sonra yapılabilir, aynı işlemi tekrarlamamak için
	--("arşiv_kontrol:\tOK"):yaz();
	islem.debug.yaz(messages.package_archive_check_ok)
	return isim,surum,devir
end

function islem.arsiv.tempdir(paket)
	-- paket arşivinin açılacağı temp dizin ayarlanması
	assert(paket,"islem.arsiv.cikar : paket is nil")
	local tempdir=kokdizin.."tmp/"..(get_basename(paket))..".tmpdir"
	assert(tempdir ~= "/tmp","islem.arsiv.cikar : tempdir must not be /tmp")
	assert(tempdir ~= "/","islem.arsiv.cikar : tempdir must not be /")
	-- paketin açılacağı tempdir oluşturma 
	local tempdir_komut=("rm -rf %s && mkdir -p %s"):format(tempdir,tempdir)
	shell(tempdir_komut)
	return tempdir.."/"
end

-- Milis paketi dışarı çıkarma/extract
function islem.arsiv.cikar(paket)
	-- ön kontrollerin yapıldığı varsayılıyor/handler func ile ?
	-- extract komutu
	local tempdir=islem.arsiv.tempdir(paket)
	assert(tempdir,"islem.arsiv.cikar : tempdir is nil")
	-- paketin açılması
	local komut=("%s xf %s -C %s"):format(arsivci,paket,tempdir)
	ret=shell(komut);
	-- arşiv çıkarılması test edilecek!!!
	local log="arşiv_çıkar:\tOK";
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
	
	return tempdir
end
------------------------------

-- Shared Libs(Paylaşılan kütüphaneler) işlemleri

islem.shlib={
	retkey="shlib:",	
	dosya="libgerekler",
}

--  -libbul
islem.api.libbul={
	usage="",
	comment="Bir .so dosyasını içeren paket veya talimatı bulur."
}
islem.api.libbul.job=function (params) 
	local shlib=nil
	local param=params[2]
	if param == "-t" then
		shlib=params[3] 
	else
		shlib=param
	end
	if shlib then
		print(islem.shlib.bul(shlib,param,"hepsi"))
	else
		messages.args_at_least_one:yaz(0)
	end
end


function islem.shlib.kontrol(tempdir)
	-- shlib kontrolü / altına kurulumlarda yapılabilir
	-- farklı bir kök altına kurulumlar için
	-- shlib dosya arama yoluyla olabilir.
	local log=""
	local ldconfig_bin="/usr/bin/ldconfig"
	if kokdizin == "/" and path_exists(ldconfig_bin) then
		assert(tempdir,"islem.shlib.kontrol : tempdir is nil")
		local shlibdos=tempdir..islem.paket.metadir..islem.shlib.dosya
		local pklibdos=tempdir..islem.paket.metadir..islem.paket.pktlib_dosya
		local iclib_kontrol=false
		if path_exists(pklibdos) then iclib_kontrol=true end
		if path_exists(shlibdos) and get_size(shlibdos) > 0 then
			local shlibs=get_content(shlibdos)
			for sh in shlibs:gmatch("[^\r\n]+") do 
				if iclib_kontrol and has_line(pklibdos,sh) then
					log="shlib.kontrol\tOK";
				elseif not islem.shlib.exist(sh) then
					(messages.shlib_not_exits..sh):yaz(3)
				end
			end
		end
		log="shlib.kontrol\tOK";
		islem.debug.yaz(log);
		islem.kur.logger:write(log.."\n")
	else
		log="shlib.kontrol\tPASS";
		islem.debug.yaz(log);
		islem.kur.logger:write(log.."\n")
	end
end

function islem.shlib.exist(shlib)
	assert(shlib,"islem.shlib.exist : shlib is nil")
	local komut="ldconfig -p | grep "..shlib.." > /dev/null;echo $?"
	--local komut='ldconfig -p | grep '..shlib..' | awk \'{split($0,a,"=> "); print a[2]}\' | xargs -r ls > /dev/null 2>&1;echo $?'
	ret=shell(komut)
	assert(ret~="","islem.shlib.exist : ret is empty")
	--print (ret,komut)
	if ret == "0" then return true end
	return false
end

function islem.shlib.bul(shlib,param,show_opt)
	assert(shlib,"islem.shlib.bul : shlib is nil")
	local opt=" | head -n1"
	if show_opt=="hepsi" then
		opt=""
	end
	if param=="-t" then
		local komut=("grep -r -i -l --include=\\%s '%s$' %s | xargs -I {} dirname {} %s "):format(islem.paket.pktlib_dosya,shlib,talimatname,opt)
		ret=shell(komut)
		if ret ~= "" then
			return ret
		end
	else
		-- todo!!! kurulu paketler için yapılacak
		return nil
	end
end
------------------------------

-- İçbilgi(mtree) işlemleri

-- içbilgi içindeki dosyaları yazdırmak
islem.api.ib={
	usage="",
	comment="",
}

islem.api.ib.job=function (params) 
	local paket=params[2]
	local ibdos=islem.icbilgi.dosyalar(kokdizin..islem.paket.vt..paket.."/")
	if ibdos then
		for _,dos in ipairs(ibdos) do
			print(dos) 
		end
	end
end

islem.icbilgi={
	retkey="icbilgi:",
	dosya=".icbilgi",	
}

function islem.icbilgi.dosyalar(tempdir)
	assert(tempdir,"islem.icbilgi.dosyalar : tempdir is nil")
	-- bu hata kullanıcı tanımlı olabilir.
	local icdosya=tempdir..islem.icbilgi.dosya
	assert(path_exists(icdosya),"islem.kur.dosya_kontrol : icbilgi is not found")
	assert(get_size(icdosya) > 0,"islem.kur.dosya_kontrol : icbilgi size equals zero")
	local tmpdos=shell("mktemp")
	local komut="zgrep -i './' "..icdosya.."| grep -v 'type=dir' | cut -d' ' -f1 > "..tmpdos
	shell(komut)
	local pdoslar=get_content(tmpdos)
	local dosyalar={}
	-- .icbilgi içindeki dosyalar döngüde tabloya eklenir.
	-- diğer dosyalar elenerek.
	for dos in pdoslar:gmatch("[^\r\n]+") do
		if dos:match(".ustbilgi")   then
		elseif dos:match("libgerekler") then
	    elseif dos:match("pktlibler")   then
	    elseif dos:match(".meta")   then
		else
			--print(dos:sub(3))
			table.insert(dosyalar,dos:sub(3))
		end
	end
	shell("rm "..tmpdos)
	return dosyalar 
end

-- sha256digest eşitliğinden match edip değer karşılaştırma
function islem.icbilgi.hash_kontrol(dir,dosya)
	assert(dir,"islem.icbilgi.hash_kontrol : dir is nil")
	local icdosya=dir..islem.icbilgi.dosya
	local komut=("zgrep -i '%s ' %s | grep -v 'type=dir' | grep -v 'type=link'"):format(dosya,icdosya)
	local ret=shell(komut)
	local hash_pattern="sha256digest=(.*)"
	local ic_hash=ret:match(hash_pattern)
	local komut2=("sha256sum %s"):format(kokdizin..dosya)
	local ret2=shell(komut2)
	local d_hash=ret2:match("%S+")
	if ic_hash == d_hash then 
		--print(dosya)
		--print(ic_hash,d_hash)
		return true 
	end
	
	return false
end

------------------Paket ve Veritabanı İşlemleri-----------------------

islem.paket={
	retkey="paket:",
	vt="var/lib/mps/db/",
	logdir="var/log/mps/",
	--cachedir="tmp",
	cachedir="var/cache/mps/depo",
	pktlib_dosya="pktlibler",
	ustbildos=".ustbilgi",
	metadir=".meta/",
}

------------------Bilgi  İşlemleri-----------------------

islem.bilgi={
	retkey="bilgi:",
	usage="mps bilgi paket_ismi",
	comment=messages.comment_mps_info,
}

function islem.bilgi.job(talimat)

	--talimatnameden bilgileri al.
	print(("ADI           : %s"):format(talimat.isim))
	print(("TANIM         : %s"):format(talimat.paket.tanim))
	print(("GRUP          : %s"):format(talimat.paket.grup))
	print(("URL           : %s"):format(talimat.paket.url))
	print(("PAKETÇİ       : %s"):format(talimat.paket.paketci))
	--paket.vt'den bilgileri al
	local pbs = islem.paket.pkvt_bilgi(talimat.isim)
	--paket.vt dosyasindaki gerekli girdileri al
	local pb = pbs[1]
	---[[
	print(("SÜRÜM         : %s"):format(pb.surum))
	print(("DEVİR         : %s"):format(pb.devir))
	print(("MİMARİ        : %s"):format(pb.mimari))
	print(("ARŞİV BOYUT   : %s"):format(pb.aboyut))
	print(("KURULUM BOYUT : %s"):format(pb.kboyut))
	--]]
end

function islem.bilgi.handler(input)
	-- işlem isminden sonra en az bir parametre olmalıdır.
	if #input > 1 then
		--islemden sonraki ilk parametreyi tek al (paket ismi) 
		local path = islem.talimat_bul.job(input[2])
		if not path then
			messages.package_not_found:format(input[2]):yaz(0)
		end
		--talimati bul ve joba gonder
		local talimat = t.get(path)
		islem.bilgi.job(talimat)
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

-- -kk kurulu kontrol 
islem.api.kk={
	usage="",
	comment="bir paketin kurulu olma durumunu verir.",
}

islem.api.kk.job=function (params) 
	local pk=params[2];
	--- todo!!!! değerlere çıktı verilecek.
	-- nil   : tanımsız
	-- true  : kurulu
	-- false : kurulu değil
	if islem.paket.kurulu_kontrol(pk) then
		messages.installed:yaz(1)
	else
		messages.not_installed:yaz(3)
	end
end

-- -kdl kurulu dosya listele
islem.api.kdl={
	usage="",
	comment="bir paketin kurulu dosyalarını listeler."
}
islem.api.kdl.job=function (params) 
	local pk=params[2];return islem.paket.kurulu_icerik(pk) 
end

-- -pkd paket kurulum doğrula
islem.api.pkd={
	usage="",
	comment="",
}

islem.api.pkd.job=function (params) 
	local pk=params[2];return islem.paket.kurulum_dogrula(pk)
end

-- -pktlib kurulu paket pktlibler
islem.api.pktlib={
	usage="",
	comment="bir paketin sağladığı .so dosyalarını listeler."
}

islem.api.pktlib.job=function (params) 
	-- bir paketin pktliblerini gösterilmesi
	-- mps -pktlib = kurulu paketin vy kaydından bakılır.
	-- mps -pktlib -t = talimatın pktlibler dosyasından bakılır.
	local pk=nil
	local param=params[2]
	if param == "-t" then
		pk=params[3] 
	else
		pk=param
	end
	if pk then
		return islem.paket.pktlibler(pk,param)
	else
		messages.args_at_least_one:yaz(0)
	end
end

--  -libgerek kurulu paket libgerekler
islem.api.libgerek={
	usage="",
	comment="bir paketin ihtiyaç duyduğu .so dosyalarını listeler."
}
islem.api.libgerek.job=function (params) 
	local pk=nil
	local param=params[2]
	if param == "-t" then
		pk=params[3] 
	else
		pk=param
	end
	if pk then
		return islem.paket.libgerekler(pk,param)
	else
		messages.args_at_least_one:yaz(0)
	end
end


-----
function islem.paket.pktlibler(paket,param)
	-- kurulu olan bir paketin pktliblerini gösterir.(shlibs)
	-- önce kurulu kontrol edilir
	assert(paket,"paket param is nil")
	local icerik=""
	-- talimatnameden bakılması istenirse
	if param == "-t" then
		local _talimatd=islem.talimat_bul.job(paket)
		if _talimatd then
			if path_exists(_talimatd.."/"..islem.paket.pktlib_dosya) then
				icerik=get_content(_talimatd.."/"..islem.paket.pktlib_dosya)
			end
			print(icerik)
		else
			(messages.talimat_not_found..paket):yaz(0)
		end
	else
		if islem.paket.kurulu_kontrol(paket) then
			local _file=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.paket.pktlib_dosya
			assert(path_exists(_file),"file not found "..islem.paket.pktlib_dosya)
			icerik=get_content(_file)
			print(icerik)
		else
			messages.package_not_installed:format(paket):yaz(0)
		end
	end
end

function islem.paket.libgerekler(paket,param)
	-- kurulu olan bir paketin gerek duyduğu libleri gösterir.(needed shlibs)
	-- önce kurulu kontrol edilir
	assert(paket,"paket param is nil")
	local icerik=""
	-- talimatnameden bakılması istenirse
	if param == "-t" then
		local _talimatd=islem.talimat_bul.job(paket)
		if _talimatd then
			if path_exists(_talimatd.."/"..islem.shlib.dosya) then
				icerik=get_content(_talimatd.."/"..islem.shlib.dosya)
			end
			print(icerik)
		else
			(messages.talimat_not_found..paket):yaz(0)
		end
	else
		if islem.paket.kurulu_kontrol(paket) then
			local _file=kokdizin..islem.paket.vt..paket.."/"..islem.paket.metadir..islem.shlib.dosya
			assert(path_exists(_file),"file not found "..islem.shlib.dosya)
			icerik=get_content(_file)
			print(icerik)
		else
			messages.package_not_installed:format(paket):yaz(0)
		end
	end
end

function islem.paket.pkvt_bilgi(paket)
	-- bir paket hakkında pkvt leri tarayarak bilgi toplar.
	local paketler={}
	local i=0
	-- isim,surum,devir,mimari,aboyut,kboyut,shasum içeriği olacak.
	local fields={"isim","surum","devir","mimari","aboyut","kboyut","shasum","depo"}
	local ret=""
	local komut='find %s -name "paket.vt#%s" -exec grep -i "^%s " {} \\; | sort -n'
	-- islem.paket.cachedir altında paketleri arayacak.
	-- {} /dev/null \; olursa eşleşen dosya ismi de gelir.
	-- en azından paket.vt#1 dosyası bulunmalıdır ki tarama yapılabilsin
	--if path_exists(islem.paket.cachedir.."/paket.vt#1") then

	for sira=1,#ayar.sunucu do
		if path_exists(kokdizin..islem.paket.cachedir.."/paket.vt#"..sira) then
			ret=shell(komut:format(kokdizin..islem.paket.cachedir,sira,paket))
			for satir in ret:gmatch("[^\r\n]+") do 
				local _paket={}
				for bilgi in satir:gmatch("%S+") do
					i = i + 1
					_paket[fields[i]]=bilgi
				end
				-- depo bilgisi conf.lua dan alınıp eklenecek.
				_paket.depo=ayar.sunucu[sira]
				table.insert(paketler,_paket)
				i=0
			end
		else
			(sira..". "..messages.paketvt_not_found):yaz(0)
		end
	end
	if #ayar.sunucu == 0 then
		messages.package_server_not_defined:yaz(3)
	end
	return paketler
end

function islem.paket.kurulu_kontrol(paket)
	-- bir paketin kurulu olup olmadığını vt e bakarak kontrol eder
	-- /var/lib/mps/DB/paket_ismi dizin kontrol eder
	-- dönğş olarak kurulu değilse nil kurulu ise link dizini döndürür.
	assert(paket,"islem.paket.kurulu_kontrol : paket is nil")
	local ret=""
	local komut='find %s -name "%s#*" -type l'
	if path_exists(kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos) then
		ret=shell(komut:format(kokdizin..islem.paket.vt,paket))
		assert(ret,paket.." link dizini yok!")
		return ret
	end
	return nil
end

function islem.paket.kurulu_icerik(paket)
	-- kurulu olan bir paketin kurulum içeriğini gösterir
	-- önce kontrol edilir
	assert(paket,"islem.paket.kurulu_kontrol : paket is nil")
	if islem.paket.kurulu_kontrol(paket) then
		local _kurulan=kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos
		assert(path_exists(_kurulan),"islem.paket.kurulu_icerik : kurulan file not found")
		local icerik=get_content(_kurulan)
		print(icerik)
		-- clear screen
		--io.write("\27[2J")
	else
		messages.package_not_installed:format(paket):yaz(0)
	end
end

function islem.paket.kurulum_dogrula(paket)
	-- kurulu olan bir paketin dosyaları incelenerek kurulum doğrulaması yapılır
	-- mevcutluk ve hash kontrolü + izinler ! todo!!!
	assert(paket,"islem.paket.kurulum_dogrula : paket is nil")
	if islem.paket.kurulu_kontrol(paket) then
		-- paket dizin kaydı
		local pdk=kokdizin..islem.paket.vt..paket.."/"
		local dosyalar=islem.icbilgi.dosyalar(pdk)
		for _,dosya in ipairs(dosyalar) do
			-- 1. dosya mevcut kontrolü
			if not path_exists(kokdizin..dosya) then
				messages.file_not_found:format(kokdizin..dosya):yaz(3)
			end
			-- 2. hash kontrolü
			if lfs.symlinkattributes(kokdizin..dosya, "mode") ~= "directory" and 
			lfs.symlinkattributes(kokdizin..dosya, "mode") ~= "link" then
				if not islem.icbilgi.hash_kontrol(pdk,dosya) then
					messages.hash_not_match:format(kokdizin..dosya):yaz(3)
				end
			end
		end
		
	else
		messages.package_not_installed:format(paket):yaz(0)
	end
end

------------------------------

------------------İndirme İşlemleri-----------------------
-- handler parametre analiz ve linki hazırlayacak
-- job direk linki hash kontrollü indirecek

islem.indir={
	retkey="indir",
	usage="mps indir paket_ismi",
	comment=messages.comment_mps_download
}

function islem.indir.handler(input)
	-- işlem isminden sonra en az bir parametre olmalıdır.
	if #input > 1 then
		local _islem=input[1]
		local pkt=input[2]
		-- ek parametreler olabilir, araştıralacak 
		local sira=1
		if input[3] then sira=tonumber(input[3]) end
		-- depolarda ilk bulduğu depodan pkvt bilgisini getirecek
		local ret=islem.paket.pkvt_bilgi(pkt)
		if ret then
			-- indir işlemi paket bilgi tablosunu kullanacak.
			if ret[sira] then
				islem.indir.job(ret[sira])
			else
				messages.package_not_found_inrepo:format(pkt):yaz(0)
			end
		else
			print(pak,"depolarda bulunamadı")
		end
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

function islem.indir.job(pb)
	-- girdi olarak paket bilgi tablosu alır.
	-- Link ve paket arşiv formatlarına ayrıştırır.
	assert(pb,"paket bilgi tablosu nil")
	-- indirilecek link ve kayıt yolu+dosya ismiyle
	function _indir(link,kayit)
		local body, code = http.request(link)
		code=tostring(code)
		if code:match("connection refused") then
			messages.server_connection_refused:format(link):yaz(3)
		elseif code=="404" then
			messages.paketvt_not_found:yaz(3)
		elseif code == "200" then
			local f = assert(io.open(kayit, 'wb'))
			f:write(body)
			f:close();
			if path_exists(kayit) then
				(link):yaz(1);
			else
				messages.redownloading:format(kayit):yaz(2)
				_indir(link,kayit);
			end
		elseif not body then 
			(link):yaz(3);
		else
			messages.unknown_error:format(link):yaz(0)
		end
	end
	
	-- arşiv formatında # , web için %23 olauyor.
	-- Bu nedenle global arşiv formatını kullanmıyoruz.
	local larsiv=("%s%%23%s-%s-%s.mps.lz"):format(pb.isim,pb.surum,pb.devir,pb.mimari)
	local arsiv=paf:format(pb.isim,pb.surum,pb.devir,pb.mimari)
	local indirilecek=true
	-- link oluşturulur
	local link=plf:format(pb.depo,larsiv)
	local kayit=kokdizin..islem.paket.cachedir.."/"..arsiv
	-- print(link,"indirilecek")
	-- indirme işlemi; indirme yöneticisine link ve kayıt yeri belirtilir.
	if path_exists(kayit) then
		-- eğer paket önbellekte var ise hash kontrolü yapılıp 
		-- hatalı ise silinip tekrar indirilir.
		if hash_check(kayit,pb.shasum) then
			indirilecek=false;
			messages.package_incache:format(pb.isim):yaz(2)
			-- paketin zaten indirilmiş olduğu-doğrulanması, dönüş kayit yol.
			return kayit
		else
			messages.package_shasum_error:format(pb.isim):yaz(3)
			messages.package_redownloading:format(pb.isim):yaz(2)
			shell("rm -f "..kayit)
		end
	end
	
	if indirilecek then
		_indir(link,kayit)
		-- shasum kontrol; indirilen dosya mevcut ve hash kontrolü yapılır.
		if path_exists(kayit) then
			if hash_check(kayit,pb.shasum) then
				messages.package_downloaded:format(pb.isim):yaz(1)
				-- paketin indirilmesi-doğrulanması, dönüş kayit yol.
				return kayit
			else
				messages.package_shasum_error:format(pb.isim):yaz(0)
			end
		else
			messages.package_download_error:format(pb.isim):yaz(0)
		end
	end
	-- diğer durumlar için nil değerin döndürülmesi
	return nil
end
------------------------------------------------------------

-- Koşuk işlemleri - kurkos,koskur,silkos, kossil

islem.kosuk={
	retkey="kosuk:",
	predos=".koskur",
	postdos=".kurkos",
	postrm=".silkos",
	prerm=".kossil",
}

-- kurmadan önce çalıştırılacak kod
function islem.kosuk.koskur(tempdir)
	local log=""
	if islem.kur.koskur then
		assert(path_exists(tempdir),"islem.kosuk.koskur : tempdir is nil")
		local kos=tempdir..islem.paket.metadir..islem.kosuk.predos
		if path_exists(kos) then
			-- koskur u çalıştıma sonuçları logla
			os.execute(kos)
			log="kosuk.koskur:\tOK"
		else
			log="kosuk.koskur:\tPASS"
		end
	else
		log="kosuk.koskur:\tDISABLE"
	end
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
end

-- kurmadan önce çalıştırılacak kod
function islem.kosuk.kurkos(tempdir)
	local log=""
	if islem.kur.kurkos then
		assert(path_exists(tempdir),"islem.kosuk.kurkos : tempdir is nil")
		local kos=tempdir..islem.paket.metadir..islem.kosuk.postdos
		if path_exists(kos) then
			-- kurkos u çalıştıma sonuçları logla
			os.execute(kos)
			log="kosuk.kurkos:\tOK"
		else
			log="kosuk.kurkos:\tPASS"
		end
	else
		log="kosuk.kurkos:\tDISABLE"
	end
	islem.debug.yaz(log);
	islem.kur.logger:write(log.."\n")
end

-- silmeden önce çalıştırılacak kod
function islem.kosuk.kossil(paket)
	assert(path_exists(kokdizin..islem.paket.vt..paket),"islem.kosuk.kossil : paketdir is nil")
	local _betik=kokdizin..islem.paket.vt..paket.."/"..islem.kosuk.prerm
	local log=""
	if path_exists(_betik) then
		-- kossil u çalıştıma sonuçları logla
		os.execute(_betik)
		log="kosuk.kossil:\tOK"
	else
		log="kosuk.kossil:\tPASS"
	end
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

-- sildikten sonra çalıştırılacak kod
function islem.kosuk.silkos(paket)
	assert(path_exists(kokdizin..islem.paket.vt..paket),"islem.kosuk.kossil : paketdir is nil")
	local _betik=kokdizin..islem.paket.vt..paket.."/"..islem.kosuk.postrm
	local log=""
	if path_exists(_betik) then
		-- silkos u çalıştıma sonuçları logla
		os.execute(_betik)
		log="kosuk.silkos:\tOK"
	else
		log="kosuk.silkos:\tPASS"
	end
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

------------------------------

-- Sil işlemleri

islem.sil={
	retkey="sil:",
	usage="mps sil paket_ismi",
	dlistfile="%stmp/%s.del.list",	
	keeplist=".silme",
	logdir=islem.paket.logdir.."sil/",
	logger=nil,
}

function islem.sil.handler(input)
	-- işlem isminden sonra en az bir parametre olmalıdır.
	if #input > 1 then
		-- sil işleri tablosu
		local remlist={}
		-- 1. girdiyi analiz et
		-- girdiler çoğul kabul edilir boşluğa göre ayrıştırılır.
		for index, _paket in ipairs(input) do
			-- ilk parametre işlem tipi olacak pas geçilir.
			if index == 1 then goto continue end
			--talimat konum bul
			local _durum=islem.paket.kurulu_kontrol(_paket)
			if _durum then
				if sil_onay then
					table.insert(remlist,_paket)
				else
					if islem.diyalog.onay(messages.confirm_package_uninstallation:format(_paket)) then
						table.insert(remlist,_paket)
					end
				end
			else
				messages.package_not_installed:format(_paket):yaz(0)
			end
			::continue::
		end
		-- eğer toplu silme yapılacaksa paket sistemine uygun sırada silinmeli
		-- re_order_delete_sensible
		--islem.sil.job(remlist);
		-- işlemlerin logu okunacak
		islem.sil.job(remlist)
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end

function islem.sil.paket(paket)
	-- tek bir paketi siler
	assert(paket,"islem.sil.paket : paket is nil")
	-- sed "s/^'/\/mnt/"  kurulan.s | sed "s/'//"
	-- sil adımları
	-- 0. logger set
	islem.sil.set_logger(paket)
	-- 1. silinecek dosya listesi hazırla
	islem.sil.prepare_list(paket)
	-- 2. silinecekleri filtrele(keeplist)
	--islem.sil.filter_list(paket)
	--islem.sil.analiz_list(paket)
	-- 3. kos-sil betiğini kontrol et / çalıştır
	islem.kosuk.kossil(paket)
	-- 4. Dosyaları güvenli! sil ve logla
	islem.sil.uygula(paket)
	-- 5. sil-kos betiğini kontrol et / çalıştır
	islem.kosuk.silkos(paket)
	-- 6. paket veritabanı güncelle sil 
	islem.sil.paket_vt(paket)
	-- silmeden sonra ld.so.cache güncellemesi için
	islem.kur.ld_update("sil");
	-- log dosyası kapatılır.
	islem.sil.logger:close();
	-- Silme işlemi sonuç kontrol
	islem.sil.bitis(paket)
end

function islem.sil.set_logger(paket)
	-- bu assert mps başına konulabilir
	assert(path_exists(kokdizin..islem.paket.logdir),"islem.sil.set_logger : islem.paket.logdir is not availables, needs mps --ilk")
	assert(path_exists(kokdizin..islem.sil.logdir),"islem.sil.set_logger : islem.sil.logdir is not availables, needs mps --ilk")
	local logfile=kokdizin..islem.sil.logdir..paket..".log"
	islem.sil.logger = assert(io.open(logfile, "w"),"islem.sil.set_logger logfile can not open")
	islem.sil.logger:write(paket.."\t"..os.date("%x %H:%M:%S").."\n");
	islem.sil.logger:write("--------------------------------------\n");
end

function islem.sil.bitis(paket)
	-- Silme adımlarının başarılı bir şekilde tamamlandığını log dosyası ile kontrol eder.
	local logfile=kokdizin..islem.sil.logdir..paket..".log"
	assert(path_exists(logfile),"islem.sil.bitis : logfile is not available")
	if not get_content(logfile):match("ERROR") then
		messages.package_uninstalled:format(paket):yaz(1)
	else
		messages.package_uninstallation_failed:format(paket):yaz(0)
	end
end

function islem.sil.prepare_list(paket)
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local _kurulan=kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos
	-- silinecek dosyaların başına kök diizn ekleyerek gerçek yollu silineceklerin oluşturulması
	--local komut='sed "s~^\'~%s~g"  %s | sed "s/\'//" > %s'
	
	-- silinecek dosyalardan ' karakterinin kaldirilmasi
	local komut="sed 's/'\\''//g' %s > %s"
	komut=komut:format(_kurulan,sildos)
	--print(komut)
	shell(komut)
	assert(get_size(sildos) > 0,"islem.sil.prepare_list : del.list is empty");
	local log="prepare_list:\tOK"
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
	--return sildos
end

function islem.sil.analiz_list(paket)
	-- paket tarafinda kurulan dizinlerin altinda paket disinda yapilan
	-- eylemler kontrol edilir, pakete ait olmayan herhangi bir dosya bulunursa
	-- dizin silinmez
	
	-- silinecek listeyi al
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local _kurulan=kokdizin..islem.paket.vt..paket.."/"..islem.kur.kurulandos
	-- check every entry if it's a file or directory
	local lines = {}
	for line in io.lines(sildos) do 
		table.insert(lines, line)
	end
	--get the list of created directories
	dirs={}
	protected_dirs={}
	for i = 1, #lines do
		local file_attr = lfs.attributes(lines[i])
		if file_attr.mode == "directory" then
			table.insert(dirs, lines[i])
		end
	end

	-- check each directory
	for i = 1, #dirs do
		-- check if there is a change in their files
		
		-- get the files from sildos file
		local files_from_sildos={}
		for j = 1, #lines do
			-- find the files starting with this dir
			if lines[j]:find(dirs[i].."/") ~= nil then
				table.insert(files_from_sildos, lines[j])
			end
		end

		-- get the files from the original directory
		local files_from_dir={}
		---[[
		for file in lfs.dir(dirs[i]) do
			if file ~= "." and file ~= ".." then
				print(dirs[i].."/"..file)
				table.insert(files_from_dir, dirs[i].."/"..file)
			end
		end
		--]]

		function find(table, item)
			for index, value in pairs(table) do
			  if value == item then
		      	return index
			  end
			end

			return -1
		end

		function find_parents(dir)
			dir_list={}
			for index, value in pairs(table) do
				--under construction
			end
		end

		-- search for differences
		if #files_from_sildos == #files_from_dir then
			for j = 1, #files_from_sildos do
				if find(files_from_dir, files_from_sildos[j]) < 0 then
					--they're not equal, so the dir should be protected
					--find its parent dirs and put them in too
					--put the dir itself
					table.insert(protected_dirs, dirs[i])
				end
			end
		end
	end

	-- remove the dir entries fromt the sildos file
	inFile = io.open(sildos, 'r')

	fileText = inFile:read('*a')
	inFile:close()

	print("dirs here ---")
	for _,v in pairs(dirs) do
		print(v)
	end
	print("  ")

	for i = 1, #dirs do
		outText = fileText:gsub(dirs[i]..'\n', '')
	end

	outFile = io.open(sildos, 'w+')
	outFile:write(outText)
	outFile:close()
	
end

function islem.sil.filter_list(paket)
	-- eğer paket dizin kaydında .silme isimli dosya varsa
	-- o dosya içindeki alt alta sıralı dosyalar silinecekler listesinden elenecektir.
	-- silinecekler başka dosya isimle içindekilerle karşılaştırılıp filtre edilenler silinir.
	local keeplistfile=kokdizin..islem.paket.vt..paket.."/"..islem.sil.keeplist
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local log=""
	if path_exists(keeplistfile) then
		local komut_k='sed "s~^~%s~g" %s > %s'
		komut_k=komut_k:format(kokdizin,keeplistfile,sildos..".keep")
		shell(komut)
		local komut_move="mv %s %s"
		shell(komut_move:format(sildos,sildos.."f"))
		local komut_f="sort %s %s |uniq -u > %s"
		komut_f=komut_f:format(sildos..".f",keeplistfile,sildos)
		shell(komut_f)
		log="filter_list:\tOK"
	else
		log="filter_list:\tPASS"
	end
	islem.debug.yaz(log)
	islem.sil.logger:write(log.."\n")
end

function islem.sil.uygula(paket)
	local sildos=islem.sil.dlistfile:format(kokdizin,paket)
	local sildos_by_user="%stmp/%s.del.list.usr"
	local sil_content=get_content(sildos);
	-- iki türlü silme stratejisi uygulanabilir
	-- 1. Lua ile döngüde kontrollü silme
	-- 2. xargs ile dosya parametreli shell ile silme
	-- bu iki yöntem incelenecek.
	local exist=true
	local delete=true
	local log=""
	local sil_komut="rm -rf %s"
	local ret=nil
	islem.sil.logger:write("---------------\n")

	to_remove={
		files={},
		dirs={}
	}

	for dos in sil_content:gmatch("[^\r\n]+") do 	
		file_attr = lfs.attributes(dos)
		if file_attr then
			if  file_attr.mode == "file" then
				table.insert(to_remove.files, dos)
			else
				_, count = dos:gsub('/', '/')
				table.insert(to_remove.dirs, {dos, count})
			end
		end
	end
	
	--[[
	print("dirs ---------------------------------------------")

	for _,v in pairs(to_remove.dirs) do
		print(v)
	end
	print("files --------------------------------------------")
	for _,v in pairs(to_remove.files) do
		print(v)
	end
	--]]

	-- first delete all the files
	for _,v in pairs(to_remove.files) do
		--print(v, "is getting deleted!")
		local result, reason = os.remove(v)
		if result then
	   		--print( "File removed")
	   	else
	  		--print("File couldn't be removed!", reason  )
	  	end
	end

	function compare(a,b)
		return a[2] > b[2]
  	end

	table.sort(to_remove.dirs, compare)

	protected_dirs={}

	-- iterate through the to_remove.dirs and delete directories if they're empty
	for i=1, #to_remove.dirs do
		--print("Current dir is", to_remove.dirs[i][1])
		status, message, code = lfs.rmdir(to_remove.dirs[i][1])
		if status == nil then
			if code == 39 then
				-- Directory is not empty, skipping deleting, put it in protected_dirs
				--print(to_remove.dirs[i][1])
				table.insert(protected_dirs, to_remove.dirs[i][1])
			else
				-- An error occurred
				hata_msg="Klasör silinemedi!".."\n"..message
				hata_msg:yaz(0)
			end
		end
	end

	--[[
	print("--")
	for i=1, #protected_dirs do
		print(protected_dirs[i])
	end
	--]]


	-- Ask user for the confirmation about the directories
	-- that are not empty
	

	if islem.diyalog.onay(messages.confirm_dir_removing_msg) then
		file = io.open(sildos_by_user:format(kokdizin,paket), "w")
		for i=1, #protected_dirs do
			file:write(protected_dirs[i].."\n")
		end
		file:close()

		messages.confirm_dir_removing_info:yaz(2)
		if islem.diyalog.onay(messages.confirm_dir_removing_cont) then
			local dirs_from_user = {}
			for line in io.lines(sildos) do 
				table.insert(dirs_from_user, line)
			end

			function find(table, item)
				for index, value in pairs(table) do
				  if value == item then
					return true
				  end
				end

				return false
			end

			function deletedir(dir)
				for file in lfs.dir(dir) do
					local file_path = dir..'/'..file
					if file ~= "." and file ~= ".." then
						if lfs.attributes(file_path, 'mode') == 'file' then
							os.remove(file_path)
							print('remove file',file_path)
						elseif lfs.attributes(file_path, 'mode') == 'directory' then
							print('dir', file_path)
							deletedir(file_path)
						end
					end
				end
				lfs.rmdir(dir)
			end


			--check for removed entries
			for i=1, #protected_dirs do
				--if it's in the protected dirs and it's not in the user edited file
				--then it should be deleted
				if not find(dirs_from_user, protected_dirs[i]) then
					--directory can contain stuff, but it should be deleted anyway
					deletedir(protected_dirs[i])
				end
			end
		end
	end
					
	
	--[[
	for i=1, #to_remove.dirs do
		print(to_remove.dirs[i][1],to_remove.dirs[i][2])
	end
	--]]
	
	--[[
	for dos in sil_content:gmatch("[^\r\n]+") do 	
		if path_exists(dos) then
			-- lua can't delete non-empty dirs / os.remove kullanım iptal
			sil_komut=sil_komut:format(dos)
			shell(sil_komut)
			sil_komut="rm -rf %s"
			if path_exists(dos) then
				islem.sil.logger:write(dos.."\t@not_delete\n")
				delete=false
			else
				islem.sil.logger:write(dos.."\tok\n")
			end
		-- dosya yoksa es geçilecek
		else
			islem.sil.logger:write(dos.."\tok\n")
			--exist=false
		end
	end
	--]]
	----------
	islem.sil.logger:write("---------------\n")
	if exist and delete then
		log="sil.uygula:  \tOK";
		islem.debug.yaz(log);
		islem.sil.logger:write(log.."\n")
	else
		log="sil.uygula:\tERROR";
		log:yaz(3);
		islem.sil.logger:write(log.."\n")
	end
end

function islem.sil.paket_vt(paket)
	local dizin=kokdizin..islem.paket.vt..paket
	assert(path_exists(dizin),"islem.sil.paket_vt : dizin is not available")
	local log=""
	local komut_vt="rm -rf %s"
	komut_vt=komut_vt:format(dizin)
	--print(komut_vt);
	shell(komut_vt);
	-- linkin de silinmesi
	shell(komut_vt.."#*");
	if not path_exists(dizin) then
		log="sil.paket_vt:\tOK";
		islem.debug.yaz(log);
		islem.sil.logger:write(log.."\n")
	else
		log="sil.paket_vt:\tERROR";
		log:yaz(3);
		islem.sil.logger:write(log.."\n")
	end
end

function islem.sil.job(jobs)
	assert(jobs,"islem.sil.job : job is nil")
	-- reorder ve ters gerek kontrolü bu safhada yapılabilir.
	for _,rpaket in ipairs(jobs) do
		-- 1. ters gereklerini kontrol et / silinecek pakete bağlı olan paketler
		islem.sil.paket(rpaket)
	end
end
------------------------------

-- Kur işlemleri

islem.kur={
	retkey="kur:",
	kurulandos="kurulan",
	dizinler={"boot","etc","usr","opt","var","tools"}, -- paket içi desteklenen dizinler
	usage="mps kur paket_ismi | paket_yolu",	
	logdir=islem.paket.logdir.."kur/",
	logger=nil,
	kurkos=true,
	koskur=true,
	zorla=false,
	comment=messages.comment_mps_install,
}

function islem.kur.agdan(paket)
	--print ("ağdan kurma TEST AŞAMASINDA!")
	assert(paket,"islem.kur.agdan : paket is nil")
	-- 1.çalışma gerekleri tespit edilecek tablo=gerek paket c
	-- islem gerek listesi global olduğu için sıfırlanması gerekir.
	islem.gerek.liste={}
	islem.gerek.job(paket,"c")
	--print(paket,#islem.gerek.liste)
	-- 2.paketvt ler den döngüde paket#surum-devir
	local ret, pk=""
	local kurliste={}
	local pkpath=nil
	-- 3. gereklerin sıralı indirme
	for _,tsd in ipairs(islem.gerek.liste) do
		-- 3.1 indirilecek size bilgi - kurulacak bilgi verilip onay ile
		pk,_=tsd:match("([%a%d-+]+)#+")
		-- paket kurulu ise atlanacak
		if islem.paket.kurulu_kontrol(pk) then
			(messages.package_already_installed..":"..pk):yaz(2);
		else
			ret=islem.paket.pkvt_bilgi(pk)[1]
			-- indirme işlemi
			-- kurliste ye inen/indirilmiş paketin yolunun kaydı
			pkpath=islem.indir.job(ret)
			if pkpath == nil then
				messages.package_dependency_dl_error:format(pk):yaz(3)
			else
				table.insert(kurliste,pkpath)
			end	
		end
		
	end
	-- 4.gerekler kurulacak (yerelden kur ile cachedir den)
	for _,pkyol in ipairs(kurliste) do
		-- 4.1 indirilecek size bilgi - kurulacak bilgi verilip onay ile
		islem.kur.yerelden(pkyol)
	end
end

function islem.kur.yerelden(paket)
	--print (paket) -- belki bu mps.log a atılabilir/nereden talimatlandığına dair
	-- yerelden gelen paketin mevcut kontrolü
	-- gönderen işlevler yapamazsa
	if not paket then
		messages.package_not_found:format(paket):yaz(0)
	end
	assert(paket ~= "","islem.kur.yerelden : paket is empty string")
	-- print (paket,"yerelden")
	-- adımlar: loglanacak, her işlem adımı log dosyasına atacak
	-- önemli not: pcall ile işlemler uygulanacak, eğer break olursa sistem kaynaklı (ctrl+c vs)
	-- işlem adımı ve onu çağıran süreç job dosyası state kayıt edilecek.
	-- -1.  paket arşivi kontrol edilir
	local isim,surum,devir=islem.arsiv.kontrol(paket)
	-- -2. logger set
	islem.kur.set_logger(isim)
	-- 0.  paket kurulu kontrol yapılır
	islem.kur.kurulu_kontrol(isim) 
	-- 1.  /tmp altında geçici bir dizine çıkarılır
	local tempdir=islem.arsiv.cikar(paket)
	-- 2.  libgerekler kontrol edilir- ldconfig sor
	islem.shlib.kontrol(tempdir) --/ kontrol altına eksik shlibleri içeren paketler kurulabilir.
	-- 3.  hedef kurulum dizininde çakışan/var olan dosya kontrolü
	islem.kur.dosya_kontrol(tempdir)
	-- 4.  koşkur varsa çalıştırılır 2.madde?
	islem.kosuk.koskur(tempdir)
	-- 5.  geçici dizinden hedef dizin altına kopyalanır
	islem.kur.kopyala(tempdir)
	-- 6.  kopyalanan dosyalar VT e yazılır, var/lib/mps/DB altına paketismi
	-- tempdir altında kurulan dosyası, .icbilgi, .ustbilgi, kosuklar, libgerekler, pktlibler
	islem.kur.vt_kayit(tempdir,isim,surum,devir)
	-- 7.  mtree ile karşılaştırma doğrulanır
	-- 8.  ldconfig güncellemesi
	islem.kur.ld_update_handler(tempdir)
	-- 9.  kurkos çalıştırılır
	islem.kosuk.kurkos(tempdir)
	-- 10. temizlik, başarı mesaj...
	islem.kur.clean_tempdir(tempdir)
	-- log dosyası kapatılır.
	islem.kur.logger:close();
	-- Paket kurulum sonucu
	islem.kur.bitis(isim)
end

function islem.kur.clean_tempdir(tempdir)
	-- kurma işlemleri bittikten sonra paket içeriğinin
	-- geçici çıkarıldığı tempdir silinir.
	local komut="rm -rf %s"
	komut=komut:format(tempdir)
	shell(komut)
end

function islem.kur.bitis(paket)
	-- Kurulum adımlarının başarılı bir şekilde tamamlandığını log dosyası ile kontrol eder.
	local logfile=kokdizin..islem.kur.logdir..paket..".log"
	assert(path_exists(logfile),"islem.kur.bitis : logfile is not available")
	if not get_content(logfile):match("ERROR") then
		messages.package_installed:format(paket):yaz(1)
	else
		messages.package_installation_failed:format(paket):yaz(0)
	end
end

function islem.kur.set_logger(paket)
	-- bu assert mps başına konulabilir
	assert(path_exists(kokdizin..islem.paket.logdir),"islem.kur.set_logger : islem.paket.logdir is not available, needs mps --ilk")
	assert(path_exists(kokdizin..islem.kur.logdir),"islem.kur.set_logger : islem.kur.logdir is not availables, needs mps --ilk")
	local logfile=kokdizin..islem.kur.logdir..paket..".log"
	--print("-",logfile)
	islem.kur.logger = assert(io.open(logfile, "w"),"islem.kur.set_logger logfile can not open")
	islem.kur.logger:write(paket.."\t"..os.date("%x %H:%M:%S").."\n");
	islem.kur.logger:write("--------------------------------------\n");
end

function islem.kur.ld_update_handler(tempdir)
	local log=""
	if path_exists(tempdir..islem.paket.metadir..islem.paket.pktlib_dosya)
	or path_exists(tempdir..islem.paket.metadir..islem.shlib.dosya) then
		-- libgerek?(kurulu ise cache edilmiş olmalı), shlib varsa ldconfig edilecek.
		islem.kur.ld_update()
		log="ld_up_handler:\tOK";
		islem.kur.logger:write(log.."\n")
	else
		messages.ld_update_pass:yaz()
		log="ld_up_handler:\tPASS";
		islem.kur.logger:write(log.."\n")
	end
end

-- kura mahsus olmasın todo!!!
function islem.kur.ld_update(oper)
	-- hedef kök dizinde ldconfig varsa güncelleme olur.
	local log=""
	if path_exists(kokdizin.."usr/bin/ldconfig")
	or path_exists(kokdizin.."sbin/ldconfig") then
		--print("ldconfig update edilecek")
		local _cachedos="etc/ld.so.cache"
		local komut1=("rm -f %s%s"):format(kokdizin,_cachedos)
		--print(komut1)
		shell(komut1)
		local komut2=("ldconfig -r %s"):format(kokdizin)
		--print(komut2)
		shell(komut2)
	else
		(messages.ld_update_pass..kokdizin):yaz()
		log="ld_update:\tPASS";
		if oper then
			islem[oper].logger:write(log.."\n")
		else
			islem.kur.logger:write(log.."\n")
		end
	end
end

function islem.kur.kopyala(tempdir)
	-- geçici çıkarma dizininden sisteme kopyala işlemi
	-- geçerli dizinler kontrol edilerek kopyalama yapılır
	-- tempdir altındaki dizinleri islem.kur.dizinler ile karşılaştır. 
	local dirs=get_dirs(tempdir)
	local kurulandos=tempdir..islem.kur.kurulandos
	assert(dirs,"islem.kur.kopyala : dirs is nil")
	--table.insert(dirs,"sbin")
	local log=""
	for _,dir in ipairs(dirs) do
		if not has_value(islem.kur.dizinler,dir) and dir.."/" ~= islem.paket.metadir then
			(messages.invalid_package_content..dir):yaz(3)
			islem.kur.logger:write(messages.invalid_package_content..dir.."\n")
		end
	end
	local komut=""
	for _,dizin in ipairs(islem.kur.dizinler) do
		if path_exists(tempdir..dizin) then
			komut='cp -v -aflr %s %s | awk \'{split($0,a,"-> "); print a[2]}\' | sed  \'s#%s#/#g\' >> %s'
			komut=komut:format(tempdir..dizin,kokdizin,kokdizin,kurulandos)
			shell(komut)
			log="kur.kopyala:\tOK";
			islem.debug.yaz(log)
			islem.kur.logger:write(log.."\n")
		end
	end
end

function islem.kur.vt_kayit(tempdir,isim,surum,devir)
	-- sisteme kopyalanan paketin paket veritabanı kaydının yapılması 
	-- ve kurulum logunun oluşturulması (adımlar loglanacak)
	assert(isim,"islem.kur.vt_kayit : isim is nil")
	local log=""
	local paket_vt_dizin=kokdizin..islem.paket.vt..isim.."/"
	-- linkin oluşturulması - indeksleme için
	local paket_vt_dizin_link=kokdizin..islem.paket.vt..isim.."#"..surum.."-"..devir
	-- paket_vt dizin oluşturma
	local komut0=("rm -rf %s"):format(paket_vt_dizin)
	shell(komut0)
	local komut1=("mkdir -p %s"):format(paket_vt_dizin)
	local komut_link=("ln -s %s %s"):format(paket_vt_dizin,paket_vt_dizin_link)
	--print(komut1)
	shell(komut1)
	shell(komut_link)
	-- / altındakileri silme engeli
	assert(paket_vt_dizin ~= "/","islem.kur.vt_kayit : paket_vt_dizin must not be /")
	-- paket_vt dizin temizlik
	local komut2=("rm -rf %s*"):format(paket_vt_dizin)
	--print(komut2)
	shell(komut2)
	-- paket.vt içerik kopyalama (tek tek bilgi dosyaları yada file olan her obje)
	-- kurulan dosyası da eklenir, islem.kur içinde tanımlandığı için burda ekliyoruz.
	-- kurulan dosyanın oluşması beklenir, oluşmadıysa sisteme dosya ve dizin kopyalama olmamıştır.
	assert(path_exists(tempdir..islem.kur.kurulandos),"islem.kur.vt_kayit : kurulan file is not available -> no files, dirs copied!!!")
	-- kurulan dosyasının paket kayıt dizine kaydı
	shell(("cp -avf %s %s"):format(tempdir..islem.kur.kurulandos,paket_vt_dizin))
	-- .meta dizini kopyala
	shell(("cp -avf %s %s"):format(tempdir..islem.paket.metadir,paket_vt_dizin))
	-- icbilgi dosyası kopyala
	shell(("cp -avf %s %s"):format(tempdir..islem.icbilgi.dosya,paket_vt_dizin))
	log="kur.vt_kayit:\tOK";
	islem.debug.yaz(log)
	islem.kur.logger:write(log.."\n")
	-- vt_kayıt test edilecek!!!
end

function islem.kur.dosya_kontrol(tempdir)
	-- sisteme kopyalanacak paket içeriğinin sistemde çakışan karşılık kontrolü
	-- çakışanlar için strateji belirlenmeli: üzerine yaz, koru vs
	local dosyalar=islem.icbilgi.dosyalar(tempdir)
	assert(dosyalar,"islem.kur.dosya_kontrol : dosyalar is nil")
	local ret=true
	local log=""
	local conflict_files={}
	for _,dosya in ipairs(dosyalar) do
		if path_exists(kokdizin..dosya) then
			(messages.file_already_exists:format(kokdizin..dosya)):yaz(3)
			table.insert(conflict_files,kokdizin..dosya)
			ret=false
		end
	end
	-- handling already exist files
	if not ret and islem.kur.zorla == false then
		if islem.diyalog.onay(messages.confirm_files_removing) then
			-- conflict_files tablosundan dosyalar sıralı şekilde silinir
			for _,dosya in ipairs(conflict_files) do
				shell("rm -f "..dosya)
			end
			log="çakışan_dosya:\tOK";
		else
			-- tempdir i sil çıkış yap
			-- print("koskurdan sonra olmalı çakşm,log da silinmeli!!! not yet")
			-- islem.kur.clean_tempdir(tempdir)
			-- os.exit() 
			log="çakışan_dosya:\tOVERRIDE";
		end
		islem.debug.yaz(log);
	else
		log="dosya_kontrol:\tOK";
		islem.debug.yaz(log);
	end
	islem.kur.logger:write(log.."\n")
end

function islem.kur.kurulu_kontrol(paket)
	-- sistemde kurulu paket kontrolü
	-- burada kurulu pakete uygulanacak seçenek sorulur
	-- sil/silme
	assert(paket,"islem.kur.kurulu_kontrol : paket is nil")
	local log=""
	if islem.paket.kurulu_kontrol(paket) then
		log=messages.package_already_installed;
		messages.package_already_installed:yaz(0);
	else
		log="kurulu_kontrol:\tOK";
	end
	islem.debug.yaz(log)
	islem.kur.logger:write(log.."\n")
end 

function islem.kur.job(kur)
	-- dikkat ! sıralı kurmayabilir tablo şeklinde geliyor
	-- işlemlerin logu hazırlanacak.
	for tip,tablo in pairs(kur) do
		-- burası sıralı iş
		if kur[tip] then
			for _,job in ipairs(tablo) do
				islem.kur[tip](job)
			end
		end
	end
end

function islem.kur.handler(input)
	-- işlem isminden sonra en az bir parametre olmalıdır.
	if #input > 1 then
		-- kurulum işleri tablosu
		local jobs={
			agdan={},
			yerelden={}
		}
		-- 1. girdiyi analiz et
		-- girdiler çoğul kabul edilir boşluğa göre ayrıştırılır.
		for index, girdi in ipairs(input) do
			-- ilk parametre işlem tipi olacak pas geçilir.
			if index == 1 then goto continue end
			--talimat konum bul
			if girdi:match("--kurkos=0") then islem.kur.kurkos=false
			elseif girdi:match("--koskur=0") then islem.kur.koskur=false
			elseif girdi:match("--zorla") or girdi:match("--force") then islem.kur.zorla=true
			elseif path_exists(girdi) and girdi:match("mps.lz") then
				-- yerelden kurulacak
				local _tk=get_abspath(girdi)
				table.insert(jobs.yerelden,_tk) 
			-- dosyadan kurulacak
			elseif girdi:match("^-%-dosya=(.*)$")  then
				local dosya=girdi:match("^-%-dosya=(.*)$")
				if path_exists(dosya) then
					for pk in (get_content(dosya)):gmatch("[^\r\n]+") do 
						local _talimatd=islem.talimat_bul.job(pk)
						if _talimatd then
							table.insert(jobs.agdan,_talimatd)
							--print(_talimatd)
						else
							(messages.talimat_not_found..pk):yaz(0)
						end
					end
				else
					messages.file_not_found:format(dosya):yaz(0)
				end
			else
				if girdi:match("/") then (messages.args_invalid..girdi):yaz(0) end
				local _talimatd=islem.talimat_bul.job(girdi)
				if _talimatd then
					-- ağdan kurulacak
					table.insert(jobs.agdan,_talimatd)
				else
					(messages.talimat_not_found..girdi):yaz(0)
				end
			end
			::continue::
		end
		islem.kur.job(jobs);
		-- todo!!! işlemlerin logu okunacak
		-- ("işlemlerin logu okunacak"):yaz(2)
	else
		(messages.usage..islem[_islem]["usage"]):yaz();
	end
end
--------------------------------------------

--------Güncelleme İşlemleri-------------------

islem.guncelle={
	retkey="guncelle:",
	comment=messages.usage_updating_repos,
	usage="mps guncelle",
	betikdepo={isim="betikdepo",tnm="Betik",path=milispath},
	talimatdepo={isim="talimatdepo",tnm="Git",path=talimatname}
}

-- apiler kısa_kodlar

-- -G paket veritabanları güncellenir.
islem.api.G={
	usage="",
	comment="",
}
islem.api.G.job=function (params) 
	local sira=params[2];return islem.guncelle.paketvt(sira)
end

-- -GG talimat depo güncellenir.
islem.api.GG={
	usage="",
	comment="",
}
islem.api.GG.job=function (params) 
	local sira=params[2];
	return islem.guncelle.gitdepo(sira,islem.guncelle.talimatdepo)
end

-- -BG betik depo güncellenir.
islem.api.BG={
	usage="",
	comment="",
}
islem.api.BG.job=function (params) 
	local sira=params[2];
	return islem.guncelle.gitdepo(sira,islem.guncelle.betikdepo)
end

-- -MG mps güncellenir.
islem.api.MG={
	usage="",
	comment=messages.comment_mps_update_self,
}

islem.api.MG.job=function (params) 
	return islem.guncelle.mps()
end

-- işlevler

function islem.guncelle.handler(input)
	assert(#input>0,"girdi eksik parametre")
	local sira=nil
	local _islem=input[1]
	if #input > 1 then sira=input[2] end
	-- mps güncelleme
	islem.guncelle.mps()
	-- talimat depolarının güncelleme
	islem.guncelle.gitdepo(sira,islem.guncelle.talimatdepo)
	-- betik depolarının güncelleme
	islem.guncelle.gitdepo(sira,islem.guncelle.betikdepo)
	-- paketvt depoları güncelleme
	islem.guncelle.paketvt(sira)
end

function islem.guncelle.mps()
	-- todo!!! mps commit hash tutulacak oradan commit değer değişimi gösterilecek
	-- değişim yoksa güncelleme yok
	assert(path_exists(mps_path),"mps_path not exist")
	assert(path_exists(mps_path.."/.git"),"invalid git directory");
	("MPS güncelleniyor:"):yaz(2);
	("------------------------------------"):yaz(2);
	local komut="cd %s && git reset --hard HEAD && git pull && chmod +x bin/mps*"
	local ret=shell(komut:format(mps_path));
	-- ret=shell(git_kont:format(repo,tmp,tmp))
	("------------------------------------"):yaz(2)
end

function islem.guncelle.paketvt(sira)
	("Paket veritaban(lar)ı güncelleniyor:"):yaz(2);
	("------------------------------------"):yaz(2);
	if not path_exists(kokdizin..islem.paket.cachedir) then
		local create_cache=("mkdir -p %s%s"):format(kokdizin,islem.paket.cachedir)
		shell(create_cache)
	end
	sira=tonumber(sira)
	local pkvt="paket.vt"
	-- işlev içinde işlev paket.vt i indirmek için
	-- paket.vt.gz gibi sıkıştırılmış gerçekleme yapılacak. todo!!!
	function _indir(sunucu,sira)
		-- io.write(sunucu.."/"..pkvt.."\t")
		local link=sunucu.."/"..pkvt
		local body, code = http.request(link)
		code=tostring(code)
		if code:match("connection refused") then
			messages.server_connection_refused:format(sunucu):yaz(3)
		elseif code=="404" then
			messages.paketvt_not_found:yaz(3)
		elseif code == "200" then
			local kayit=kokdizin..islem.paket.cachedir.."/"..pkvt.."#"..sira
			local f = assert(io.open(kayit, 'wb'))
			f:write(body)
			f:close();
			-- ("+"):yaz(1);
			--kayit:yaz(2);
			if path_exists(kayit) then
				(link):yaz(1);
			else
				messages.redownloading:format(kayit):yaz(2)
				_indir(sunucu,sira);
			end
		elseif not body then 
			(link):yaz(3);
		else
			messages.unknown_error:format(link):yaz(0)
		end
	end
	
	-- eğer sadece bir paket sunucu güncellenmek istenirse
	if sira then 
		-- sıra aşımlı paket vt güncelelnmek istenirse
		if #ayar.sunucu < sira then 
			messages.package_db_out_of_order:yaz(0)
		end
		if ayar.sunucu[sira]  then
			_indir(ayar.sunucu[sira],sira)
		end
	-- çoklu sunucu güncelleme
	else
		for _sira,sunucu in ipairs(ayar.sunucu) do
			_indir(sunucu,_sira)
		end
	end
	("------------------------------------"):yaz(2);
end

function islem.guncelle.gitdepo(sira,depo)
	-- tip=betikdepo, gitdepo
	-- depo={isim="betikdepo",tnm="Betik",path=milispath}
	-- depo={isim="gitdepo",tnm="Git",path=talimatname}
	-- bin, ayarlar lı betikdepo güncelleme yapılacak todo!!!
	assert(depo,"depo is nil!!!");
	(depo.tnm.." depoları güncelleniyor:"):yaz(2);
	("------------------------------------"):yaz(2);
	function do_clone(repo,path)
		local komut="git clone %s %s"
		local ret=shell(komut:format(repo,path))
	end
	
	function do_pull(path)
		assert(path_exists(path.."/.git"),"invalid git directory")
		local komut="cd %s && git pull"
		local ret=shell(komut:format(path))
	end
	
	function esitle(repoyol,altdizin,hedef)
		-- todo!!! eşitlenecek dizinden sadece talimat içeren
		-- dizinleri alarak eşitleme yap veya sonda silme
		local komut="cp -rf %s/%s/* %s/"
		if path_exists(repoyol.."/"..altdizin) then
			shell(komut:format(repoyol, altdizin ,hedef))
		else
			messages.git_repo_subdir_not_found:yaz(0)
		end
	end
	
	function yedekle(dizin)
		local komut="mv %s %s.old"
		if path_exists(dizin) then
			shell(komut:format(dizin,dizin))		
		end
		-- dizin yedeklenerek yeni boş oluşturulur.
		assert(lfs.mkdir(dizin),dizin.." oluşturulamadı.")
	end
	
	local _repo=""
	local _repoyol=""
	local duzey=""
	local tmp=shell("mktemp")
	
	local eskisil="rm -rf %s.old"
	-- git repo mevcut kontrol komut
	local git_kont="git ls-remote -q %s > %s  2>&1;cat %s | head -n1 | awk '{print $1}'"
	-- !!! burası farklı ayar.betikdepo
	for bdepo,repolar in pairs(ayar[depo.isim]) do
		-- !!! burası farklı
		duzey=depo.path.."/"..bdepo
		-- her talimat-betik düzeyinde yedekleme-eşitleme-eskiyi silme yapılacak
		yedekle(duzey)
		
		for repo,dizin in pairs(repolar) do
			-- git repo mevcut kontrolü
			ret=shell(git_kont:format(repo,tmp,tmp))
			io.write(bdepo," ",repo," ",dizin)
			if ret:match("fatal") then
				("\t-"):yaz(1)
			else
				-- Git işlemleri
				-- repo netde mevcut ise, yerelde yoksa clone varsa pull yapılacak.
				_repo=repo:gsub("https://", "")
				_repo=_repo:gsub("http://", "")
				_repo=_repo:gsub("/", ".")
				print("\t",_repo)
				_repoyol=kokdizin..ayar.repo_dizin.."/".._repo
				if path_exists(_repoyol) then
					do_pull(_repoyol)
				else
					do_clone(repo, _repoyol)
				end
				-- Eşitleme işlemleri
				esitle(_repoyol,dizin,duzey)
			end
		end
		-- sıra-talimat düzeyi işlemler bittikten sonra .old düzey silinir.
		if path_exists(duzey..".old") then
			shell(eskisil:format(duzey))
		end
	end
	shell(("rm -f %s"):format(tmp));
	("------------------------------------"):yaz(2);
end


-- Mps İşlemleri ----------------------------

-- -v ile mps sürüm no gösterilir.
islem.api.v={
	usage="",
	comment="",
}
islem.api.v.job=function() islem.surum.handler() end

-- -ayar öntanımlı ayarlar yükler/kopyalar

islem.ayarla={
	retkey="ayarla:",
	comment=messages.usage_configure,
	usage="mps ayarla",
}

function islem.ayarla.handler()
	-- mps için conf.lua yükleme komutu
	local komut="cp -f %s/conf/conf.lua.sablon %s/conf/conf.lua"
	shell(komut:format(mps_path,mps_path))
end

islem.mps={
	retkey="mps:",
	version="MPS 2.0.4 - Milis Paket Sistemi milisarge@gmail.com",	
	_comment=messages.usage_mps,
}

islem.surum={}

function islem.surum.handler()
	islem.mps.version:yaz(2)
end

------------------------------------------------------------

-- -h mps yardım gösterilir.
islem.api.h={
	usage="",
	comment="",
}
islem.api.h.job=function() islem.help.handler() end
islem.help={
	retkey="yardım:",
	usage="mps -h",	
}

function islem.help.handler()
	local aralik=":"
	print(messages.help)
	print("-----------------")
	for key,_ in pairs(islem) do
		aralik=":"
		if islem[key]["comment"] then
			if #key<7 then aralik="\t:" end
			print(key,aralik.." "..islem[key]["comment"])
		end
	end
	print("-----------------")
	for key,_ in pairs(islem.api) do
		aralik=":"
		if islem.api[key]["comment"] then
			if #key<7 then aralik="\t:" end
			print("-"..key,aralik.." "..islem.api[key]["comment"])
		end
	end
end

-----------------------------------------

-- Debug işlemleri

islem.debug={
	retkey="debug",	
}

function islem.debug.yaz(log)
	if debug then
		if log then
			log:yaz()
		else
			messages.empty_log:yaz(0)
		end
	end
end
-----------------------------------------


-- İşlevlerin Test İşlemi ----------------------------
-- islem.a.b.c işleminin tesit için . karakterine göre ayrıştırıp
-- dizide öyle çağırmak gerekir.

islem.test={
	retkey="test:",
}

islem.api.test={
	usage="",
	comment="",
}
islem.api.test.job=function() islem.test.case1() end

function islem.test.handler(f1)
	local islev=f1[2]
	assert(islev,"islem.test.handler : f1 is nil")
	print (islev);
	islem.test[islev]()
	_G[islev]()
end

function islem.test.case1()
	print(hash_check("/tmp/ttt","sadsfsef"))
end

function islem.test.hello()
	print("merhaba")
end

function hello()
	print("merhaba2")
end

-----------------------------------------

-- parse arguments / burası sadece ana parsing olsun
-- her işlemin girdi parseri ayrı olacak
-- ilk parametre işlem olmalı
if #arg < 1 then
	-- en az bir parametre belirtilmeli
	--messages.args_at_least_one:yaz(0)
	-- yardım menüsünün gösterilmesi
	print(islem.mps.version)
	print(islem.mps._comment)
	islem.help.handler()
	os.exit();
end

-- cli arg to global params variable
params=arg
-- bu aşamada --color gibi çıktı tipleri vs opsiyonlar elimine edilmeli
-- sonra sadeleşmiş hedef işlem ve girdileri kalmalı

-- global ayarlar analiz edilir

authorised_check()
color_check()
debug_check()
root_check()
mps_init_check()
mps_initfs_check()
confirm_check()

-- mps için gerekli init dizinlerin kontrolü
-- req_dir_check()

--en son parametreler sadeleştirilir (false paramlar silinir)
re_param()

-- ilk paramtre olarak işlem gelmeli
_islem=params[1]

if _islem == nil then os.exit() end

local _api=""
if _islem:sub(0,1) == "-" then
	_api=_islem:sub(2)
end

if islem[_islem] then
	function tprint_new (tbl, indent)
	  if not indent then indent = 0 end
	  for k, v in pairs(tbl) do
		formatting = string.rep("  ", indent) .. k .. "-> "
		if type(v) == "table" then
		  print(formatting)
		  tprint_new(v, indent+1)
		elseif type(v) == 'boolean' then
		  print(formatting .. tostring(v))
		elseif type(v) == "function" then
		  print(formatting.."function")
		else
		  print(formatting .. v)
		end
	  end
	end


	-- print(_islem," işlemi yapılacak")
	-- ilgili işlem kuralı çağıralacak /handler veya handler olabilir.
	-- param analiz ve thread tanımlama işleri için
	-- işlem parseri geri kalan parametreleri analiz edecek
	local key = "handler"
	if islem[_islem][key] then
		islem[_islem]["handler"](params)
	else
		(messages.handler_not_found.._islem):yaz(0)
	end
-- - ile başlayan parametreleri işleyebilmek için
-- -kk ı kk ile islem.api içinde kontro edip
-- ilgili işlevi çağıracak.
elseif islem.api[_api] then
	islem.api[_api]["job"](params)
	--_G[islem.api[_api]](params)
else
	(messages.args_invalid.._islem):yaz(0)
end

-- todo list
--[[
("---------TODO-LIST------------------"):yaz(1);
("mtree s256sum sorun !!!"):yaz();
("pktlibler so düzgün tespit edilemiyor/ncurses bknz"):yaz();
("talimatın yanndaki dosyalar/yama vs"):yaz();
("çakışan dosyaları oto sil-onsistemde lazım oluyor"):yaz();
("thash olayı derle.sh gibi dosyalar da olunca mantıklı olmuyor!-talimat dizini kamusun hashle"):yaz();
("paket sil.logda harici diizn yerine kokdizinsiz yazdırma"):yaz();
("pktlib,libgerek tespitinde eksiklik ve harici dizinle yazılıyor!"):yaz();
("kurulumda kurkos pasif ederek kurdurma"):yaz();
("-y veya işlem onay parametresi eklenecek-genele/kur-işlem bazlı?"):yaz();
("SİLKOŞ - KOŞSİL TEST EDİLECEK"):yaz();
("shell komutları uygulandığına dair assert(veya expect) edilmeli -"):yaz();
("------------------------------------"):yaz(1);
]]--
